﻿/*****************************************************************************//*!
* file  : can quene.c
* creat : apleilx
* data  : 2017/11/05
*******************************************************************************/
#include "os_obj.h"
#include "pincfg.h"
#include "sys_init.h"
#include "common.h"
#include "bsp_hal.h"
#include "can_quene.h"
#include "sys_ext.h"
#include "str_ext.h"
#include "can_task.h"

simp_can_frame_ctr_type can1_quene;

static simp_can_frame_type can_rx_buff[32];
static simp_can_frame_type can_tx_buff[64];
static simp_can_frame_type can_tx_rt_buff[32];
static simp_can_cmd_type   stc_cmd[16];
static simp_can_cmd_type   sync_cmd[8];

#define can_quene		can1_quene
#define can_port		CAN1

/*******************************************************************************
* @brief  isr enable or disable
* \param[in] none
* \retval: none
*******************************************************************************/
#define can_rx_intx_enable() \
	can_port->INTEN |= CAN_INTEN_RFPIE0 | CAN_INTEN_RFPIE1;

#define can_tx_intx_enable()  can_port->INTEN |= CAN_INTEN_TSMEIE
#define can_tx_intx_disable() can_port->INTEN &= ~CAN_INTEN_TSMEIE

/*******************************************************************************
* @brief  isr
* \param[in] none
* \retval: none
*******************************************************************************/
void USB_HP_CAN1_TX_IRQHandler(void)
{
	//清除中断标志
	can_port->TSTS |= CAN_TSTS_RQC0 | CAN_TSTS_RQC1 | CAN_TSTS_RQC2;
		
	if(can_quene.tx_st == SIMP_CAN_TX_WAIT_TE)
	{
		can_quene.tx_st = SIMP_CAN_TX_IDLE;
		can_tx_intx_disable();
	}
	else
	{
		//继续发送
		while(can_port->TSTS & CAN_TSTS_TSME)
		{
			if(SIMP_CAN_TX_IDLE == simp_can_transmit(&can_quene))
			{
				break;
			}
		}
	}
}

/*******************************************************************************
* @brief  isr
* \param[in] none
* \retval: none
*******************************************************************************/
void USB_LP_CAN1_RX0_IRQHandler(void)
{
	simp_can_frame_type rcv;
	CanRxMsg rxmsg;
		
	CAN_Receive(can_port, CAN_FIFO0, &rxmsg);
	
	rcv.len = rxmsg.DLC;
	copy_u8(rxmsg.Data, rcv.dat, rcv.len);
	
	rcv.remot = (rxmsg.RTR == CAN_RTR_DATA)?0:1;
	
	if(rxmsg.IDT == CAN_ID_STD)
	{
		rcv.id = rxmsg.StdId;
		rcv.id_mode = SIMP_CAN_ID_MODE_STD;
	}
	else
	{
		rcv.id = rxmsg.ExtId;
		rcv.id_mode = SIMP_CAN_ID_MODE_EXT; 
	}
	
	simp_can_receive(&can_quene, &rcv);

	can_rx_intx_enable();
}

/*******************************************************************************
* @brief  isr
* \param[in] none
* \retval: none
*******************************************************************************/
void CAN1_RX1_IRQHandler(void)
{
	simp_can_frame_type rcv;
	CanRxMsg rxmsg;
		
	CAN_Receive(can_port, CAN_FIFO1, &rxmsg);
	
	rcv.len = rxmsg.DLC;
	copy_u8(rxmsg.Data, rcv.dat, rcv.len);
	
	rcv.remot = (rxmsg.RTR == CAN_RTR_DATA)?0:1;
	
	if(rxmsg.IDT == CAN_ID_STD)
	{
		rcv.id = rxmsg.StdId;
		rcv.id_mode = SIMP_CAN_ID_MODE_STD;
	}
	else
	{
		rcv.id = rxmsg.ExtId;
		rcv.id_mode = SIMP_CAN_ID_MODE_EXT; 
	}
	
	simp_can_receive(&can_quene, &rcv);

	can_rx_intx_enable();
}

/*******************************************************************************
* @brief  isr
* \param[in] none
* \retval: none
*******************************************************************************/
void CAN1_SCE_IRQHandler(void)
{
	
}

/*******************************************************************************
* @brief  can1 quene send to port
* \param[in] frame: can frame
* \retval: none
*******************************************************************************/
static void can_tx_send_reg(simp_can_frame_type * frame)
{
	CanTxMsg txmsg;

	if (0 ==  (can_port->TSTS & CAN_TSTS_TSME))
	{
		can_tx_intx_enable();
		return;
	}

	txmsg.DLC = frame->len;
	txmsg.ExtId = frame->id;
	txmsg.StdId = frame->id;
	txmsg.RTR = frame->remot ? CAN_RTR_REMOTE : CAN_RTR_DATA;
	txmsg.IDT = (frame->id_mode == SIMP_CAN_ID_MODE_STD) ? \
		CAN_ID_STD : CAN_ID_EXT;
	((uu32*)(&txmsg.Data[0]))[0] = ((uu32*)frame->dat)[0];
	((uu32*)(&txmsg.Data[0]))[1] = ((uu32*)frame->dat)[1];
	
	CAN_Transmit(can_port, &txmsg);

	can_tx_intx_enable();

	can_isr_print("@< %d ms >::CAN1 Send data \r", app_tick_get());
}

/*******************************************************************************
* @brief  can1 quene receive handle
* \param[in] none
* \retval: none
*******************************************************************************/
void can1_rx_handle(simp_can_frame_type * frame)
{
	can_dbg_print("@< %d ms >::CAN1 receive frame:", app_tick_get(), frame->remot?"ROT":"DAT");
	can_dbg_print("id = 0x%08X, Len = %d: ", frame->id, frame->len);
	can_dbg_print("dat = 0x%04X, 0x%04X, 0x%04X, 0x%04X\n", frame->dat[0].uval, frame->dat[1].uval, frame->dat[2].uval, frame->dat[3].uval);
}

/*******************************************************************************
* @brief  can1 quene receive handle
* \param[in] none
* \retval: none
*******************************************************************************/
static void can_time_run(void)
{
	simp_can_time_run(&can_quene);
}

/*******************************************************************************
* @brief  is_tx_hal_empty
* \param[in] none
* \retval: none
*******************************************************************************/
static uint8_t is_tx_hal_empty(void)
{
	if((can_port->TSTS & CAN_TSTS_TSME) == CAN_TSTS_TSME)
		return 1;
	return 0;
}

static uint8_t is_tx_hal_full(void)
{
	if((can_port->TSTS & CAN_TSTS_TSME) == 0)
		return 1;
	return 0;
}

/*******************************************************************************
* @brief  can quene init
* \param[in] none
* \retval: none
*******************************************************************************/
static void quene_obj_init(void)
{
	intx_alloc();
	
	memset(&can_quene, 0, sizeof(can_quene));

	can_quene.rx_frame = can_rx_buff;
	can_quene.rx_buff_amount = sizeof(can_rx_buff) / sizeof(simp_can_frame_type);

	can_quene.tx_frame = can_tx_buff;
	can_quene.tx_buff_amount = sizeof(can_tx_buff) / sizeof(simp_can_frame_type);

	can_quene.tx_rt_frame = can_tx_rt_buff;
	can_quene.tx_rt_buff_amount = sizeof(can_tx_rt_buff) / sizeof(simp_can_frame_type);
	
	can_quene.tx_send = can_tx_send_reg;
	can_quene.rx_handle = can1_rx_handle;
	can_quene.is_tx_hal_empty = is_tx_hal_empty;
	can_quene.is_tx_hal_full = is_tx_hal_full;
	
	simp_can_cmd_init(
		&can_quene,
		stc_cmd,
		sizeof(stc_cmd)/sizeof(simp_can_cmd_type),
		sync_cmd,
		sizeof(sync_cmd)/sizeof(simp_can_cmd_type));
	
	intx_disable();

	vtask_list_add(&app_tick_task_list, can_time_run);

	intx_enable();
}

/*******************************************************************************
* @brief  can quene init
* \param[in] none
* \retval: none
*******************************************************************************/
void can1_quene_init(void)
{
	CAN_InitType par;
	can_baud_cal_type baud;
	RCC_ClockType clk;
	
	// 时钟开启
	RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_CAN1, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1PERIPH_CAN1, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1PERIPH_CAN1, DISABLE);
	
	// 波特率计算
	RCC_GetClocksFreq(&clk);
	baud.div_max = 256;
	baud.sjw_max = 4;
	baud.bs1_max = 16;
	baud.bs2_max = 8;
	baud.bs_min = 7;
	baud.clk = clk.APB1CLK_Freq;
	baud.baud_set = 200000;
	can_buad_cal(&baud);
	
	// 初始化
	par.CAN_Mode = CAN_Mode_Normal;
	par.CAN_Prescaler = baud.div;
	par.CAN_SJW = baud.sjw - 1;
	par.CAN_BS1 = baud.bs1 - 1;
	par.CAN_BS2 = baud.bs2 - 1;
	par.CAN_TTC = DISABLE;
	par.CAN_ABO = ENABLE;
	par.CAN_AWU = ENABLE;
	par.CAN_NART = DISABLE;
	par.CAN_RFL = DISABLE;
	par.CAN_TFP = ENABLE;
	
	CAN_Init(can_port, &par);
	
	/* Request initialisation */
  	can_port->MCTRL |= CAN_MCTRL_INRQ ;
	can_port->MCTRL &= ~(uint32_t)0x10000;
	can_port->MCTRL &= ~(uint32_t)CAN_MCTRL_INRQ;

	quene_obj_init();
	
	can_rx_intx_enable();
	
	// 中断
	nvic_irq_set(USB_HP_CAN1_TX_IRQn, 3, 1);
	nvic_irq_set(USB_LP_CAN1_RX0_IRQn, 3, 1);
	nvic_irq_set(CAN1_RX1_IRQn, 3, 1);
	nvic_irq_set(CAN1_SCE_IRQn, 3, 0);
}

